package com.lp.mgt.configs.shiro;


import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.lp.mgt.entities.Menu;
import com.lp.mgt.entities.Role;
import com.lp.mgt.entities.User;
import com.lp.mgt.services.UserService;
import com.lp.mgt.utils.ShrioUtil;

public class ShiroRealm extends AuthorizingRealm {
	 private Logger logger = LoggerFactory.getLogger(AuthorizingRealm.class);
	@Autowired
	private UserService userService;
	
	//认证.登录
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
		logger.info("---------------- 执行 Shiro 凭证认证 ----------------------");
		 UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
		String username =token.getUsername();
		if(username==null) {
			logger.info("username is null");
		}
		//通过username从数据库中查找 User对象.
		User user = userService.findUserByName(username);
		if(user == null){
			throw new UnknownAccountException("没有找到用户 [" + username + "]");
		}
		  // 用户为禁用状态
        if (!"1".equals(user.getState())) {
            throw new DisabledAccountException("用户["+username+"]被锁定");
        }
		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
				user, //这里传入的是user对象，比对的是用户名，直接传入用户名也没错，但是在授权部分就需要自己重新从数据库里取权限
				user.getPassword(), //密码散列值
				ByteSource.Util.bytes(user.getSalt()),//salt=username+"shiro"
				this.getClass().getName()  //realm name
				);
		return authenticationInfo;
	}

	
	//授权
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		logger.info("---------------- 执行 Shiro 权限获取 ---------------------");
	    //获取登录用户
		Object principal = principals.getPrimaryPrincipal();
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		if (principal instanceof User) {
			User oldUser=(User) principal;
			//编辑菜单后需要删除缓存重新授权，调用该方法。所以需要需要重新low数据
			User user=userService.findUserByName(oldUser.getUsername());
			logger.info("用户账号："+user.getUsername());
				for(Role r:user.getRoles()){
					logger.info("角色有:"+r.getRoleName());
					authorizationInfo.addRole(r.getRoleKey());//角色
					for(Menu m:r.getMenus()){
						if(m!=null&&!"".equals(m.getPerms())&&m.getPerms()!=null) {//由于这个判断，菜单（如系统工具，权限模块）的perm字段不能为空。
							logger.info("********权限有:"+m.getMenuName()+"【"+m.getPerms()+"】");
							authorizationInfo.addStringPermission(m.getPerms());//操作权限
						}
		        }
			}
			ShrioUtil.setSysUser(user);//重新加载Principal
		}
		 logger.info("---------------- Shiro 权限获取成功 ----------------------");
		 return authorizationInfo;
	}
	
    /**
     * 清理缓存权限
     */
    public void clearCachedAuthorizationInfo()
    {
        this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
    }

}
